/**
 * 版权所有 (c) 2018，《自制AI图像搜索引擎》作者。

 * 您可以下载和使用该软件。但它仅供个人学习和研究使用，禁止任何商业用途。

 * 您必须在此软件的所有副本（包括任何修改或衍生版本）中保留此许可证文件，且不能对其有任何修改。

 * 欢迎购买《自制AI图像搜索引擎》——一本全面介绍AI图像搜索引擎原理与实现的书。如有任何意见或建议，请发送邮件至imgsearch@126.com。
 */
package com.ai.deepsearch;

import be.tarsos.lsh.Vector;
import org.apache.commons.io.FileUtils;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentMap;

/**
 * 查找相似图像
 */
public class Classify {

    public static List<Vector> getVectorListFromDB(String dbPath) {
        DB db = DBMaker.fileDB(dbPath).make();
        ConcurrentMap<String, double[]> map = db.hashMap("feat_map", Serializer.STRING, Serializer.DOUBLE_ARRAY).open();
        List<Vector> vecs = new ArrayList<Vector>();
        for (String key : map.keySet()) {
            double[] val = map.get(key);
            // norm2
            val = Utils.normalizeL2(val);
            Vector vec = new Vector(key, val);
            vecs.add(vec);
        }
        db.close();
        return vecs;
    }

    public static void kmeans(String dbPath,String fromPath,String distPath,Integer k) throws IOException {
        Long time=System.currentTimeMillis();
        List<Vector> dataset = Classify.getVectorListFromDB(dbPath);
        int m=0;
        if(k!=null){
            m=k;
        }else{
            Canopy canopy = new Canopy(new ArrayList<>(dataset));
            m = canopy.cluster();
        }

        System.out.println("预计 "+m+" 个分类");
        Kmeans cu = new Kmeans(new ArrayList<>(dataset));
        cu.execute(m);

        ArrayList<ArrayList<Vector>> clusters = cu.getCluster();
        int i=0;
        for (ArrayList<Vector> cluster : clusters) {

            for (Vector vector : cluster) {
                System.out.println("move "+vector.getKey()+" "+i);
                moveFile(vector.getKey(),i,fromPath,distPath);
            }

            i++;

        }

        System.out.println("耗时 "+((System.currentTimeMillis()-time)/1000/60)+" min");
    }

    public static void moveFile(String from,int to,String fromPath,String distPath) throws IOException {
        String baseDir=fromPath;
        String distDir=distPath;
        File toF = new File(distDir+File.separator+to);
        if(!toF.isDirectory()){
            toF.mkdir();
        }
        FileUtils.copyFile(new File(baseDir+ File.separator+from),new File(toF.getPath()+File.separator+from));
    }



}
